﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace WareHouse.Service.Services
{
    using System.Collections.ObjectModel;
    using System.Data;
    using System.Data.Entity.Migrations;
    using System.Data.Objects.DataClasses;
    using System.Globalization;
    using System.Runtime.Remoting.Contexts;
    using System.Runtime.Remoting.Messaging;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Policy;
    using System.Transactions;

    using global::WareHouse.Contract.Services;

    using WareHouse.Contract.Common;
    using WareHouse.Contract.Models;
    using WareHouse.Data;
    using AutoMapper;

    using WareHouse.Service.MapperProfile;

    using IsolationLevel = System.Transactions.IsolationLevel;

    public class WareHouseService : ServiceBase, IWareHouseService
    {
        private readonly InitialMapper initialMapper;
        public WareHouseService()
        {
            // init mapper
            initialMapper=new InitialMapper();
        }
        #region Security Hoang.Nguyen Minh

        /// <summary>
        /// The login with user name and password.
        /// parameter 0 : login succeed or not
        /// parameter 1  : isAdmin or not
        /// parameter 2 : username
        /// paramenter 3 : group user id
        /// </summary>
        public UserAccountModel LoginWithUserNameAndPassword(string userName, string password)
        {
            var resultLogin = new List<object> { false, false,"",0};
            var encryptPassword = MD5Encrypt(password.Trim());
            var check =
                this.wareHouseContext.UserAccounts.FirstOrDefault(x => x.UserName == userName.Trim() && x.Password == encryptPassword);
            return Mapper.Map<UserAccountModel>(check);
        }
        #endregion

        #region Agency Hoang.Nguyen Minh
        public List<AgencyModel> ListAgency()
        {
         
             var listAgency = wareHouseContext.Agencies
                    .ToList();
             return listAgency != null
                 ?  listAgency.Select(x => Mapper.Map<AgencyModel>(x)).ToList():new List<AgencyModel>();
        }


        public AgencyModel SaveOrUpdateAgency(AgencyModel model)
        {
            var entity = Mapper.Map<Agency>(model);
            if (model.IsCurrent)
            {
                

                foreach (var itemPrice in wareHouseContext.Agencies.Where(x => x.IsCurrent))
                {
                    itemPrice.IsCurrent = false;
                }




            }
            if (model.AgencyId > 0)
            {

                // update
                if (this.IsHaveCurrentAgency(entity.AgencyId) == false)
                {
                    entity.IsCurrent = true;
                }

                var entry = wareHouseContext.Entry(entity);
                
                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Agency>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.AgencyId == entity.AgencyId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<AgencyModel>(entity);
            }
            // update
            if (this.IsHaveCurrentAgency(entity.AgencyId) == false)
            {
                entity.IsCurrent = true;
            }
            wareHouseContext.Agencies.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<AgencyModel>(entity);

        }

        public bool DeleteAgency(AgencyModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<Agency>(model);
                    context.Agencies.Attach(entity);
                    context.Agencies.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {
                
                return false;
            }
        }

        public AgencyModel GetCurrentAgency()
        {
            var currentAgency = wareHouseContext.Agencies.FirstOrDefault(x => x.IsCurrent);
            return currentAgency != null ? Mapper.Map<AgencyModel>(currentAgency):null;
        }

        #endregion

        #region Company Hoang.Nguyen Minh
        public List<CompanyModel> ListCompany()
        {

            var listCompany = wareHouseContext.Companies
                   .ToList();
            return listCompany != null
                ? listCompany.Select(x => Mapper.Map<CompanyModel>(x)).ToList() : new List<CompanyModel>();
        }


        public CompanyModel SaveOrUpdateCompany(CompanyModel model)
        {
            var entity = Mapper.Map<Company>(model);
           
            if (model.CompanyId > 0)
            {

                // update
              

                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Company>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.CompanyId == entity.CompanyId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<CompanyModel>(entity);
            }
            // update
            
            wareHouseContext.Companies.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<CompanyModel>(entity);

        }

        public bool DeleteCompany(CompanyModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<Company>(model);
                    context.Companies.Attach(entity);
                    context.Companies.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }
        public CompanyModel GetcompanyBycompanyId(int companyId)
        {
            var company = wareHouseContext.Companies.FirstOrDefault(x => x.CompanyId==companyId);
            return company != null ? Mapper.Map<CompanyModel>(company) : null;
        }

      

        #endregion



        #region Unit Hoang.Nguyen Minh
        public List<UnitModel> ListUnit()
        {

            var listUnit = wareHouseContext.Units
                   .ToList();
            return listUnit != null
                ? listUnit.Select(x => Mapper.Map<UnitModel>(x)).ToList():new List<UnitModel>();
        }


        public UnitModel SaveOrUpdateUnit(UnitModel model)
        {
            var entity = Mapper.Map<Unit>(model);
            if (model.UnitId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Unit>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.UnitId == entity.UnitId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<UnitModel>(entity);
            }
            // update
            wareHouseContext.Units.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<UnitModel>(entity);

        }

        public bool DeleteUnit(UnitModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<Unit>(model);
                    context.Units.Attach(entity);
                    context.Units.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion


        #region ItemType Hoang.Nguyen Minh
        public List<ItemTypeModel> ListItemType()
        {

            var listItemType = wareHouseContext.ItemTypes
                   .ToList();
            return listItemType != null
                ?  listItemType.Select(Mapper.Map<ItemTypeModel>).ToList():new List<ItemTypeModel>();
        }


        public ItemTypeModel SaveOrUpdateItemType(ItemTypeModel model)
        {
            var entity = Mapper.Map<ItemType>(model);
            if (model.ItemTypeId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<ItemType>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.ItemTypeId == entity.ItemTypeId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<ItemTypeModel>(entity);
            }
            // update
            wareHouseContext.ItemTypes.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<ItemTypeModel>(entity);

        }

        public bool DeleteItemType(ItemTypeModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<ItemType>(model);
                    context.ItemTypes.Attach(entity);
                    context.ItemTypes.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion


        #region Group User Hoang.Nguyen Minh
        public List<GroupUserModel> ListGroupUser()
        {

            var listGroupUser = wareHouseContext.GroupUsers
                   .ToList();
            return listGroupUser != null
                ? listGroupUser.Select(Mapper.Map<GroupUserModel>).ToList() : new List<GroupUserModel>();
        }

        public List<GroupUserModel> ListGroupUserWithoutAdministratorGroup()
        {

            var listGroupUser = wareHouseContext.GroupUsers
                   .Where(x => x.GroupUserName.ToLower() != "administrators");
            
            return listGroupUser != null
                ? listGroupUser.Select(Mapper.Map<GroupUserModel>).ToList() : new List<GroupUserModel>();
        }
        

        public GroupUserModel SaveOrUpdateGroupUser(GroupUserModel model)
        {
            var entity = Mapper.Map<GroupUser>(model);
            if (model.GroupUserId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<GroupUser>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.GroupUserId == entity.GroupUserId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<GroupUserModel>(entity);
            }
            // update
            wareHouseContext.GroupUsers.Add(entity);
            // add role to detail

            var listRole = wareHouseContext.Roles.ToList();


            foreach (var role in listRole)
            {
                Detail_GroupUserRole detail = new Detail_GroupUserRole
                {
                    GroupUserId = entity.GroupUserId,
                    Permit = false,
                    RoleId = role.RoleId

                };
                wareHouseContext.Detail_GroupUserRole.Add(detail);
            }
           
            wareHouseContext.SaveChanges();
            return Mapper.Map<GroupUserModel>(entity);

        }

        public bool DeleteGroupUser(GroupUserModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<GroupUser>(model);
                    context.GroupUsers.Attach(entity);
                    context.GroupUsers.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion
        

        #region Item Hoang.Nguyen Minh
        public List<ItemModel> ListItem()
        {
            var listItem = wareHouseContext.Items.ToList();
            return
               listItem != null
                       ?  listItem.Select(
                    x =>
                    
                        new ItemModel
                            {
                                DateCreate = x.DateCreate,
                                EffectiveFromDate = x.EffectiveFromDate,
                                EffectiveToDate = x.EffectiveToDate,
                                ItemId = x.ItemId,
                                ItemName = x.ItemName,
                                ItemShortName = x.ItemShortName,
                                ItemTypeId = x.ItemTypeId,
                                UserCreate = x.UserCreate,
                                ItemTypeName = x.ItemType.ItemTypeName,
                                LastUpdate = x.LastUpdate,
                                UnitId = x.UnitId,
                                UnitName = x.Unit.UnitName,
                                UpdateBy = x.UpdateBy,
                                
                            }).ToList():new List<ItemModel>();
        }

        public ItemModel SaveOrUpdateItem(ItemModel model)
        {
            var entity = Mapper.Map<Item>(model);
            if (model.ItemId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Item>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.ItemId == entity.ItemId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<ItemModel>(entity);
            }
            // update
            wareHouseContext.Items.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<ItemModel>(entity);

        }

        public bool DeleteItem(ItemModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<Item>(model);
                    context.Items.Attach(entity);
                    context.Items.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        public List<ItemModel> ListItemByWareHouseId(int wareHouseId)
        {

            var listItem = wareHouseContext.DetailItemWareHouses.Where(x=>x.WareHouseId== wareHouseId).ToList();
            return
                listItem != null
                       ? listItem.Select(
                    x =>
                    {
                       
                        return new ItemModel
                             {
                           
                                 ItemId = x.ItemId,
                                 Quantity = x.Quantity ,
                                 ItemName = x.Item.ItemName,
                                 ItemPriceId =
                                     x.Item.ItemPrices.FirstOrDefault(y => y.IsCurrentPrice)!=null
                                         ? x.Item.ItemPrices.FirstOrDefault(y => y.IsCurrentPrice).ItemPriceId
                                         : 0,
                                 CurrentPrice =
                                    x.Item.ItemPrices.FirstOrDefault(y => y.IsCurrentPrice)!=null
                                         ? x.Item.ItemPrices.FirstOrDefault(y => y.IsCurrentPrice).Value
                                         : 0
                             } ;
                    }).ToList():new List<ItemModel>();

        }

        public List<ItemModel> ListItemByWareHouseIdForImport()
        {

            var listItem = wareHouseContext.Items.ToList();
            return
                listItem != null
                       ? listItem.Select(
                    x =>
                   new ItemModel
                   {

                       ItemId = x.ItemId,
                       
                       ItemName = x.ItemName,
                       ItemPriceId =
                           x.ItemPrices.Count > 0
                               ? x.ItemPrices.FirstOrDefault(y => y.IsCurrentPrice).ItemPriceId
                               : 0,
                       CurrentPrice =
                           x.ItemPrices.Count > 0
                               ? x.ItemPrices.FirstOrDefault(y => y.IsCurrentPrice).Value
                               : 0
                   }).ToList() : new List<ItemModel>();

        }

        #endregion

        #region Item Price Hoang.Nguyen Minh
        public List<ItemPriceModel> ListItemPriceByItemId(int itemId)
        {

            var listItem = wareHouseContext.ItemPrices.ToList();
            return
               listItem != null
                       ?  listItem.Where(x => x.ItemId == itemId).Select(
                    x =>
                    new ItemPriceModel
                        {
                            DateCreate = x.DateCreate,
                            EffectiveFromDate = x.EffectiveFromDate,
                            EffectiveToDate =x.EffectiveToDate,
                            ItemId = x.ItemId,
                            ItemName = x.Item.ItemName,
                            ItemPriceId = x.ItemPriceId,
                            UserCreate = x.UserCreate,
                            LastUpdate = x.LastUpdate,
                            UpdateBy = x.UpdateBy,
                            Value = x.Value,
                            IsCurrentPrice = x.IsCurrentPrice
                        }).ToList():new List<ItemPriceModel>();
        }

        public ItemPriceModel SaveOrUpdateItemPrice(ItemPriceModel model)
        {
            var entity = Mapper.Map<ItemPrice>(model);
            if (model.IsCurrentPrice)
            {


                foreach (var itemPrice in wareHouseContext.ItemPrices.Where(x =>x.ItemId == entity.ItemId && x.IsCurrentPrice))
                {
                    itemPrice.IsCurrentPrice = false;
                }



            }

         
    

            if (model.ItemPriceId > 0)
            {
                var checkIsAnyCurrentPrice =
                    wareHouseContext.ItemPrices.Count(x => x.ItemId != entity.ItemId && x.IsCurrentPrice);
                if (checkIsAnyCurrentPrice <= 0)
                {
                    entity.IsCurrentPrice = true;
                }

                // update

                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<ItemPrice>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.ItemPriceId == entity.ItemPriceId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                }
                wareHouseContext.SaveChanges();

                return Mapper.Map<ItemPriceModel>(entity);
            }
            // update
            if (this.IsHaveCurrentPrice(entity.ItemId) == false)
            {
                entity.IsCurrentPrice = true;
            }
            wareHouseContext.ItemPrices.Add(entity);
            
            wareHouseContext.SaveChanges();
            return Mapper.Map<ItemPriceModel>(entity);

        }

        public bool DeleteItemPrice(ItemPriceModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<ItemPrice>(model);
                    context.ItemPrices.Attach(entity);
                    context.ItemPrices.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        public bool IsCheckOverLapItemPrice(int itemPriceId, DateTime effectiveFrom, DateTime? effectiveTo, int itemId)
        {
            if (itemPriceId == 0)
            {
                var currentSorPrice =
                    this.wareHouseContext.ItemPrices.Count(x => x.ItemId == itemId &&((effectiveTo == null && x.EffectiveToDate == null)
                                                                 ||
                                                                 (effectiveTo == null && x.EffectiveToDate != null && effectiveFrom >= x.EffectiveFromDate
                                                                  && effectiveFrom <= x.EffectiveToDate)
                                                                 || (effectiveTo == null && x.EffectiveToDate != null && effectiveFrom <= x.EffectiveFromDate)
                                                                 || (effectiveTo != null && x.EffectiveToDate == null && effectiveTo >= x.EffectiveFromDate)
                                                                 ||
                                                                 (effectiveFrom != null && effectiveTo != null && x.EffectiveFromDate != null
                                                                  && x.EffectiveToDate != null && effectiveTo >= x.EffectiveFromDate
                                                                  && effectiveTo <= x.EffectiveToDate)
                                                                 ||
                                                                 (effectiveFrom != null && effectiveTo != null && x.EffectiveFromDate != null
                                                                  && x.EffectiveToDate != null && effectiveFrom >= x.EffectiveFromDate
                                                                  && effectiveFrom <= x.EffectiveToDate)
                                                                 ||
                                                                 (effectiveFrom != null && effectiveTo != null && x.EffectiveFromDate != null
                                                                  && x.EffectiveToDate != null && effectiveFrom <= x.EffectiveFromDate
                                                                  && effectiveTo >= x.EffectiveToDate)));

                if (currentSorPrice == 0)
                {
                    return true;
                }

                return false;
            }
            else
            {
                var currentSorPrice =
                    this.wareHouseContext.ItemPrices.Count(x => x.ItemId == itemId && x.ItemPriceId != itemPriceId
                                                                && ((effectiveTo == null && x.EffectiveToDate == null)
                                                                    ||
                                                                    (effectiveTo == null && x.EffectiveToDate != null && effectiveFrom >= x.EffectiveFromDate
                                                                     && effectiveFrom <= x.EffectiveToDate)
                                                                    || (effectiveTo == null && x.EffectiveToDate != null && effectiveFrom <= x.EffectiveFromDate)
                                                                    || (effectiveTo != null && x.EffectiveToDate == null && effectiveTo >= x.EffectiveFromDate)
                                                                    ||
                                                                    (effectiveFrom != null && effectiveTo != null && x.EffectiveFromDate != null
                                                                     && x.EffectiveToDate != null && effectiveTo >= x.EffectiveFromDate
                                                                     && effectiveTo <= x.EffectiveToDate)
                                                                    ||
                                                                    (effectiveFrom != null && effectiveTo != null && x.EffectiveFromDate != null
                                                                     && x.EffectiveToDate != null && effectiveFrom >= x.EffectiveFromDate
                                                                     && effectiveFrom <= x.EffectiveToDate)
                                                                    ||
                                                                    (effectiveFrom != null && effectiveTo != null && x.EffectiveFromDate != null
                                                                     && x.EffectiveToDate != null && effectiveFrom <= x.EffectiveFromDate
                                                                     && effectiveTo >= x.EffectiveToDate)));

                if (currentSorPrice == 0)
                {
                    return true;
                }

                return false;
            }
        }

        public bool IsHaveCurrentPrice(int itemId)
        {
            var result = wareHouseContext.ItemPrices.Count(x => x.ItemId == itemId && x.IsCurrentPrice);
            if (result > 0)
            {
                return true;
            }
            return false;

        }

        public bool IsHaveCurrentAgency(int agencyId)
        {
            var result = wareHouseContext.Agencies.Count(x => x.AgencyId == agencyId && x.IsCurrent);
            if (result > 0)
            {
                return true;
            }
            return false;

        }

        public ItemPriceModel GetPriceInPast(DateTime dateCreateExport, int itemId)
        {
            var result =
                this.wareHouseContext.ItemPrices.FirstOrDefault(
                    x =>
                    x.ItemId == itemId
                    && ((x.EffectiveFromDate <= dateCreateExport && x.EffectiveToDate >= dateCreateExport)
                        || (x.EffectiveFromDate <= dateCreateExport && x.EffectiveToDate == null)));
            if (result != null)
            {
                return Mapper.Map<ItemPriceModel>(result);
            }
            return null;
        }

        #endregion

        #region WareHouse

        public List<WareHouseModel> LoadWareHouseSales()
        {
            var listWareHouse = wareHouseContext.WareHouses.Where(x => x.IsSale).ToList();
            return listWareHouse  != null
                ?  listWareHouse.Select(Mapper.Map<WareHouseModel>).ToList():new List<WareHouseModel>();
        }

        public List<WareHouseModel> ListWareHouse()
        {
            var listWareHouse = wareHouseContext.WareHouses.ToList();
            return listWareHouse != null
                       ? listWareHouse.Select(
                           x =>
                           new WareHouseModel
                               {
                                   WareHouseId = x.WareHouseId,
                                   WareHouseName = x.WareHouseName,
                                   IsSale = x.IsSale,
                                   WareHouseDescription = x.WareHouseDescription,
                                   WareHouseTypeId = x.WareHouseTypeId,
                                   WareHouseTypeName = x.WareHouseType.WareHouseTypeName,
                                   DateCreate = x.DateCreate,
                                   EffectiveFromDate = x.EffectiveFromDate,
                                   EffectiveToDate = x.EffectiveToDate,
                                   LastUpdate = x.LastUpdate,
                                   UserCreate = x.UserCreate,
                                   UpdateBy = x.UpdateBy
                               }).ToList()
                       : new List<WareHouseModel>();
        }

        #endregion

        #region Export

        public string GetExport()
        {
           
            var export = wareHouseContext.Exports.OrderByDescending(x => x.ExportId).FirstOrDefault();
            var exportId = "";
            if (export!=null)
            {
                var id = int.Parse(export.ExportId.Substring(3));
                id += 1;
                exportId = "HDX" + string.Format("{0:00}", id);
                return exportId;

            }
            exportId = "HDX01";
            return exportId;
        }


        public bool SaveExport(ExportModel model)
        {
            try
            {



                var entity = Mapper.Map<Export>(model);

                // update
                wareHouseContext.Exports.Add(entity);
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                throw ex;
            }
           
            
        }

        public bool SaveExportDetail(List<ExportDetailModel> listModel, ExportModel exportModel)
        {
            try
            {
                var listEntity = Mapper.Map<List<ExportDetailModel>, List<ExportDetail>>(listModel);
                
                // update
                foreach (var item in listEntity)
                {
                    wareHouseContext.ExportDetails.Add(item);

                    //update quantity in ware house
                    foreach (var item1 in wareHouseContext.DetailItemWareHouses.Where(x => x.ItemId == item.ItemId && x.WareHouseId == exportModel.WareHouseId))
                    {
                        item1.Quantity = item1.Quantity - item.Quantity;
                    }
                    var track =
                        this.wareHouseContext.ExportHistories.Count(x => x.DateLog == exportModel.DateCreate.Date && x.ItemId == item.ItemId
                                                                    && x.WareHouseId == exportModel.WareHouseId);
                    if (track==0)
                    {
                        wareHouseContext.ExportHistories.Add(
                           new ExportHistory
                           {
                               DateLog = exportModel.DateCreate.Date,
                               ItemId = item.ItemId,
                               WareHouseId = exportModel.WareHouseId,
                               QuantityExist = listModel.FirstOrDefault(x => x.ItemId == item.ItemId).QuantityBegining
                           });
                    }
                  
                }
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }


        public List<ExportModel> ListAllExport()
        {
            var result =
                wareHouseContext.Exports.Select(
                    x =>
                    new ExportModel
                        {
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.FullName,
                            DateCreate = x.DateCreate,
                            ExportId = x.ExportId,
                            IsDebt = x.IsDebt,
                            LastUpdate = x.LastUpdate,
                            UpdateBy = x.UpdateBy,
                            UserCreate = x.UserCreate,
                            WareHouseId = x.WareHouseId,
                            WareHouseName = x.WareHouse.WareHouseName,
                            EmployerName = x.UserAccount.FullName
                            
                        }).ToList();
            return result;
        }

        public List<ExportDetailModel> ListItemByExportId(string exportId)
        {
            var result =
                wareHouseContext.ExportDetails.Where(x => x.ExportId == exportId).Select(
                    d =>
                    new ExportDetailModel
                        {
                            ExportId = d.ExportId,
                            CurrentPrice = (float)d.ItemPrice.Value,
                            ItemId = d.ItemId,
                            ItemName = d.Item.ItemName,
                            Quantity = d.Quantity,
                            Total = (float)(d.Quantity * d.ItemPrice.Value)
                        }).ToList();
            return result;
        }

        public bool UpdateQuantityInExported(EditExpAndImpModel editExpAndImpModel)
        {
            var check = editExpAndImpModel.QuantityOrginal - editExpAndImpModel.QuantityChangeTo;
            try
            {
                foreach (var item1 in wareHouseContext.DetailItemWareHouses.Where(x => x.ItemId == editExpAndImpModel.ItemId && x.WareHouseId == editExpAndImpModel.WareHouseId))
                {

                    item1.Quantity = item1.Quantity + check;
                }

                foreach (var item1 in wareHouseContext.ExportDetails.Where(x => x.ItemId == editExpAndImpModel.ItemId && x.Export.WareHouseId == editExpAndImpModel.WareHouseId))
                {

                  

                    if (check > 0)
                    {
                        item1.Quantity = item1.Quantity - check;
                    }
                    else
                    {
                        item1.Quantity = item1.Quantity + (check*(-1));
                    }
                }

                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }
        public bool CheckQuantityInWareHouse(EditExpAndImpModel editExpAndImpModel)
        {
            var check = 0;
            if (editExpAndImpModel.QuantityChangeTo>editExpAndImpModel.QuantityOrginal)
            {
                check = editExpAndImpModel.QuantityChangeTo - editExpAndImpModel.QuantityOrginal;
            }
            check = editExpAndImpModel.QuantityOrginal - editExpAndImpModel.QuantityChangeTo;
            var result =
                this.wareHouseContext.DetailItemWareHouses.FirstOrDefault(x => x.ItemId == editExpAndImpModel.ItemId && x.WareHouseId == editExpAndImpModel.WareHouseId).Quantity;
            if (result!=null)
            {
                if (result >= check)
                {
                    return true;
                }
            }
            return false;
        }

        public List<CustomerDebtModel> ListItemByCustomerId(int customerId)
        {
            var listItems =
                wareHouseContext.ExportDetails.Where(x => x.Export.CustomerId == customerId && x.Export.IsDebt)
                    .Select(x => new CustomerDebtModel
                                     {
                                         ItemId = x.ItemId,
                                         ItemName = x.Item.ItemName,
                                         ExportId = x.ExportId,
                                         Price = x.ItemPrice.Value,
                                         Quantity = x.Quantity,
                                         DateCreate = x.Export.DateCreate
                                         
                                     }).ToList();
            if (listItems.Count > 0)
            {
                foreach (var item in listItems)
                {
                    item.TaxRate = this.GetTaxRateByYearMonthAndCustomerId(
                        item.DateCreate.Year,
                        item.DateCreate.Month,
                        customerId);
                    item.TotalWithNotTax = item.Price * item.Quantity;
                    item.TotalWithTax = item.TotalWithNotTax
                                        +  (item.TotalWithNotTax * (decimal)(item.TaxRate / 100));
                }
            }
            return listItems;
        }
        public List<CustomerDebtModel> ListItemByCustomerId(int customerId, DateTime effectiveFromDate, DateTime effectiveTodate)
        {
            var listItems =
                wareHouseContext.ExportDetails.ToList().Where(
                    x =>
                    x.Export.CustomerId == customerId && x.Export.IsDebt
                    && (x.Export.DateCreate.Date >= effectiveFromDate && x.Export.DateCreate.Date <= effectiveTodate))
                    .Select(
                        x => new CustomerDebtModel
                                 {
                        ItemName = x.Item.ItemName,
                        ExportId = x.ExportId,
                        Price = x.ItemPrice.Value,
                        Quantity = x.Quantity,
                        DateCreate = x.Export.DateCreate

                    }).ToList();
            if (listItems.Count > 0)
            {
                foreach (var item in listItems)
                {
                    item.TaxRate = this.GetTaxRateByYearMonthAndCustomerId(
                        item.DateCreate.Year,
                        item.DateCreate.Month,
                        customerId);
                    item.TotalWithNotTax = item.Price * item.Quantity;
                    item.TotalWithTax = item.TotalWithNotTax
                                        + (item.TotalWithNotTax * (decimal)(item.TaxRate / 100));
                }
            }
            return listItems;
        }
        private float GetTaxRateByYearMonthAndCustomerId(int year, int month, int customerId)
        {
            double taxRate = 0;
            CustomerDebtRate customerDebtRate;
            switch (month)
            {
                case 1:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month1;
                    }
                    break;
                case 2:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month2;
                    }
                    break;
                case 3:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month4;
                    }
                    break;
                case 4:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month4;
                    }
                    break;
                case 5:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month5;
                    }
                    break;
                case 6:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month6;
                    }
                    break;
                case 7:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month7;
                    }
                    break;
                case 8:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month8;
                    }
                    break;
                case 9:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month9;
                    }
                    break;
                case 10:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month10;
                    }
                    break;
                case 11:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month11;
                    }
                    break;
                case 12:
                    customerDebtRate = this.wareHouseContext.CustomerDebtRates.FirstOrDefault(x => x.CustomerId == customerId && x.Year == year);
                    if (
                        customerDebtRate != null)
                    {
                        taxRate = customerDebtRate.Month12;
                    }
                    break;

            }
            return (float)taxRate;
        }


        #endregion


        #region Customer Hoang.Nguyen Minh
        public List<CustomerModel> ListCustomer()
        {

            var listCustomer = wareHouseContext.Customers
                   .ToList();
            return listCustomer != null
                ?  listCustomer.Select(x => Mapper.Map<CustomerModel>(x)).ToList():new List<CustomerModel>();
        }


        public CustomerModel SaveOrUpdateCustomer(CustomerModel model)
        {
            var entity = Mapper.Map<Customer>(model);
            if (model.CustomerId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Customer>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.CustomerId == entity.CustomerId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<CustomerModel>(entity);
            }
            // update
            wareHouseContext.Customers.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<CustomerModel>(entity);

        }

        public bool DeleteCustomer(CustomerModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<Customer>(model);
                    context.Customers.Attach(entity);
                    context.Customers.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        public CustomerModel GetCustomerByCustomerId(int customerId)
        {
            var customer = wareHouseContext.Customers.FirstOrDefault(x => x.CustomerId == customerId);
            return customerId != null ? Mapper.Map<CustomerModel>(customer) : null;
        }

        #endregion


        #region Department Hoang.Nguyen Minh
        public List<DepartmentModel> ListDepartment()
        {

            var listDepartment = wareHouseContext.Departments
                   .ToList();
            return listDepartment != null
                ?  listDepartment.Select(Mapper.Map<DepartmentModel>).ToList():new List<DepartmentModel>();
        }


        public DepartmentModel SaveOrUpdateDepartment(DepartmentModel model)
        {
            var entity = Mapper.Map<Department>(model);
            if (model.DepartmentId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Department>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.DepartmentId == entity.DepartmentId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<DepartmentModel>(entity);
            }
            // update
            wareHouseContext.Departments.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<DepartmentModel>(entity);

        }

        public bool DeleteDepartment(DepartmentModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<Department>(model);
                    context.Departments.Attach(entity);
                    context.Departments.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion

        #region Employer Hoang.Nguyen Minh
        public List<EmployerModel> ListEmployer()
        {

            var listEmployer = wareHouseContext.Employers
                   .ToList();
            return listEmployer != null
                       ? listEmployer.Select(Mapper.Map<EmployerModel>).ToList()
                       : new List<EmployerModel>();
        }


        public EmployerModel SaveOrUpdateEmployer(EmployerModel model)
        {
            var entity = Mapper.Map<Employer>(model);
            if (model.EmployerId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Employer>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.EmployerId == entity.EmployerId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<EmployerModel>(entity);
            }
            // update
            wareHouseContext.Employers.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<EmployerModel>(entity);

        }

        public bool DeleteEmployer(EmployerModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<Employer>(model);
                    context.Employers.Attach(entity);
                    context.Employers.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion


        #region CustomerDebtRate Hoang.Nguyen Minh
        public List<CustomerDebtRateModel> ListCustomerDebtRate()
        {

            var listCustomerDebtRate = wareHouseContext.CustomerDebtRates
                   .ToList();
            return listCustomerDebtRate != null
                ? listCustomerDebtRate.Select(x => Mapper.Map<CustomerDebtRateModel>(x)).ToList() : new List<CustomerDebtRateModel>();
        }

        public CustomerDebtRateModel SaveOrUpdateCustomerDebtRate(CustomerDebtRateModel model)
        {
            var entity = Mapper.Map<CustomerDebtRate>(model);
            if (this.CheckExistCustomerDebtRate(entity))
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<CustomerDebtRate>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.Year == entity.Year && d.CustomerId == entity.CustomerId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<CustomerDebtRateModel>(entity);
            }
            // update
            wareHouseContext.CustomerDebtRates.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<CustomerDebtRateModel>(entity);

        }

        private bool CheckExistCustomerDebtRate(CustomerDebtRate entity)
        {
            return this.wareHouseContext.CustomerDebtRates.Count(x=>x.CustomerId == entity.CustomerId && x.Year == entity.Year) > 0;
        }

        public bool DeleteCustomerDebtRate(CustomerDebtRateModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<CustomerDebtRate>(model);
                    context.CustomerDebtRates.Attach(entity);
                    context.CustomerDebtRates.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion


        #region Import

        public string GetImport()
        {

            var Import = wareHouseContext.Imports.OrderByDescending(x => x.ImportId).FirstOrDefault();
            var ImportId = "";
            if (Import != null)
            {
                var id = int.Parse(Import.ImportId.Substring(3));
                id += 1;
                ImportId = "HDN" + string.Format("{0:00}", id);
                return ImportId;

            }
            ImportId = "HDN01";
            return ImportId;
        }


        public bool SaveImport(ImportModel model)
        {
            try
            {



                var entity = Mapper.Map<Import>(model);

                // update
                wareHouseContext.Imports.Add(entity);
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                throw ex;
            }


        }

        public bool SaveImportDetail(List<ImportDetailModel> listModel, ImportModel ImportModel)
        {
            try
            {
                var listEntity = Mapper.Map<List<ImportDetailModel>, List<ImportDetail>>(listModel);

                // update
                foreach (var item in listEntity)
                {
                    wareHouseContext.ImportDetails.Add(item);

                    List<DetailItemWareHouse> listResult =
                        wareHouseContext.DetailItemWareHouses.Where(
                            x => x.ItemId == item.ItemId && x.WareHouseId == ImportModel.WareHouseId).ToList();
                    //update quantity in ware house
                    if (listResult.Count > 0)
                    {
                        foreach (var item1 in listResult)
                        {
                            item1.Quantity = item1.Quantity + item.Quantity;
                            break;

                        }
                    }
                    else
                    {
                        wareHouseContext.DetailItemWareHouses.Add(
                            new DetailItemWareHouse
                                {
                                    ItemId = item.ItemId,
                                    Quantity = item.Quantity,
                                    WareHouseId = ImportModel.WareHouseId
                                });
                    }




                }
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        public List<ImportModel> ListAllImport()
        {
            var result =
                wareHouseContext.Imports.Select(
                    x =>
                    new ImportModel
                    {
                       
                        DateCreate = x.DateCreate,
                        ImportId = x.ImportId,
                        LastUpdate = x.LastUpdate,
                        UpdateBy = x.UpdateBy,
                        UserCreate = x.UserCreate,
                        WareHouseId = x.WareHouseId,
                        WareHouseName = x.WareHouse.WareHouseName,
                        EmployerName = x.UserAccount.FullName

                    }).ToList();
            return result;
        }

        public List<ImportDetailModel> ListItemByImportId(string ImportId)
        {
            var result =
                wareHouseContext.ImportDetails.Where(x => x.ImportId == ImportId).Select(
                    d =>
                    new ImportDetailModel
                    {
                        ImportId = d.ImportId,
                        Price = d.Price,
                        ItemId = d.ItemId,
                        ItemName = d.Item.ItemName,
                        Quantity = d.Quantity,
                        Total = d.Quantity * d.Price
                    }).ToList();
            return result;
        }

        public bool UpdateQuantityInImported(EditExpAndImpModel editExpAndImpModel)
        {
            var check = editExpAndImpModel.QuantityOrginal - editExpAndImpModel.QuantityChangeTo;
            try
            {
                foreach (var item1 in wareHouseContext.DetailItemWareHouses.Where(x => x.ItemId == editExpAndImpModel.ItemId && x.WareHouseId == editExpAndImpModel.WareHouseId))
                {

                    item1.Quantity = item1.Quantity + check;
                }

                foreach (var item1 in wareHouseContext.ImportDetails.Where(x => x.ItemId == editExpAndImpModel.ItemId && x.Import.WareHouseId == editExpAndImpModel.WareHouseId))
                {



                    if (check > 0)
                    {
                        item1.Quantity = item1.Quantity - check;
                    }
                    else
                    {
                        item1.Quantity = item1.Quantity + (check * (-1));
                    }
                }

                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }

        #endregion


        #region WareHouseType Hoang.Nguyen Minh
        public List<WareHouseTypeModel> ListWareHouseType()
        {

            var listWareHouseType = wareHouseContext.WareHouseTypes
                   .ToList();
            return listWareHouseType != null
                ? listWareHouseType.Select(Mapper.Map<WareHouseTypeModel>).ToList() : new List<WareHouseTypeModel>();
        }


        public WareHouseTypeModel SaveOrUpdateWareHouseType(WareHouseTypeModel model)
        {
            var entity = Mapper.Map<WareHouseType>(model);
            if (model.WareHouseTypeId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<WareHouseType>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.WareHouseTypeId == entity.WareHouseTypeId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<WareHouseTypeModel>(entity);
            }
            // update
            wareHouseContext.WareHouseTypes.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<WareHouseTypeModel>(entity);

        }

        public bool DeleteWareHouseType(WareHouseTypeModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<WareHouseType>(model);
                    context.WareHouseTypes.Attach(entity);
                    context.WareHouseTypes.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion


        #region WareHouse Hoang.Nguyen Minh

        public WareHouseModel SaveOrUpdateWareHouse(WareHouseModel model)
        {
            var entity = Mapper.Map<WareHouse>(model);
            if (model.WareHouseId > 0)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<WareHouse>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.WareHouseId == entity.WareHouseId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<WareHouseModel>(entity);
            }
            // update
            wareHouseContext.WareHouses.Add(entity);
            wareHouseContext.SaveChanges();
            return Mapper.Map<WareHouseModel>(entity);

        }

        public bool DeleteWareHouse(WareHouseModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<WareHouse>(model);
                    context.WareHouses.Attach(entity);
                    context.WareHouses.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        #endregion

        #region Manage Customer Debt
        public bool SavesDetailCustomerPaidHistory(List<DetailCustomerPaidHistoryModel> listModel)
        {
            try
            {
                foreach (var item in listModel)
                {
                    var entity = Mapper.Map<DetailCustomerPaidHistory>(item);

                    if (item.CustomerPaidHistoryId > 0)
                    {
                        wareHouseContext.DetailCustomerPaidHistories.Add(entity);
                    }


                }
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception)
            {

                return false;
            }




        }

        public bool SetExportIsPaidTrueToFalse(List<ExportModel> listExportModel)
        {
            try
            {
                foreach (var export in listExportModel)
                {
                    foreach (var item in wareHouseContext.Exports.Where(x => x.ExportId == export.ExportId))
                    {
                        item.IsDebt = false;
                    }

                }
                
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception)
            {
                
                return false;
            }
            
        }

        public bool SetAllCustomerPaidHistoryIsEndFalseToTrueByCustomerId(int customerId)
        {
            try
            {
                foreach (var item in wareHouseContext.CustomerPaidHistories.Where(x => x.CustomerId == customerId))
                {
                    item.IsEnd = true;
                }

                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception)
            {

                return false;
            }

        }



        public CustomerPaidHistoryModel SaveOrUpdateCustomerPaidHistory(CustomerPaidHistoryModel model)
        {
            var entity = Mapper.Map<CustomerPaidHistory>(model);
            if (model.CustomerPaidHistoryId > 0)
            {

                // update

                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<CustomerPaidHistory>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.CustomerPaidHistoryId == entity.CustomerPaidHistoryId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<CustomerPaidHistoryModel>(entity);
            }
            // update
            wareHouseContext.CustomerPaidHistories.Add(entity);
            wareHouseContext.SaveChanges();
            if (entity != null)
            {
                return Mapper.Map<CustomerPaidHistoryModel>(entity);
            }
            return new CustomerPaidHistoryModel();
        }

        public CustomerPaidHistoryModel AddMoreMoney(CustomerPaidHistoryModel model)
        {
            var entity = Mapper.Map<CustomerPaidHistory>(model);
            if (model.CustomerPaidHistoryId > 0)
            {

                // update

                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<CustomerPaidHistory>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.CustomerPaidHistoryId == entity.CustomerPaidHistoryId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<CustomerPaidHistoryModel>(entity);
            }
            // update
            wareHouseContext.CustomerPaidHistories.Add(entity);
            wareHouseContext.SaveChanges();
            if (entity != null)
            {
                return Mapper.Map<CustomerPaidHistoryModel>(entity);
            }
            return new CustomerPaidHistoryModel();
        }


        public bool EndDebtForCustomer(List<DetailCustomerPaidHistoryModel> listDetailCustomerPaidHistory, CustomerPaidHistoryModel customerPaidHistoryModel, List<ExportModel> listExportModel)
        {
            var customerPaidHistoryId =
                this.SaveOrUpdateCustomerPaidHistory(customerPaidHistoryModel).CustomerPaidHistoryId;
            if (customerPaidHistoryId > 0)
            {
                foreach (var c in listDetailCustomerPaidHistory)
                {
                    c.CustomerPaidHistoryId = customerPaidHistoryId;
                }

                if (SetExportIsPaidTrueToFalse(listExportModel))
                {
                    if (SavesDetailCustomerPaidHistory(listDetailCustomerPaidHistory))
                    {
                        this.SetAllCustomerPaidHistoryIsEndFalseToTrueByCustomerId(customerPaidHistoryModel.CustomerId);
                        return true;
                    }
                
                }
            }
            return false;
        }
        public decimal GetTotalDebt(int customerId)
        {
            var listItem = this.ListItemByCustomerId(customerId);
            var result = listItem != null ? listItem.Sum(x => x.TotalWithTax) : 0;
            return result;
        }

        public decimal GetTotalCustomerPaidButNotEnd(int customerId)
        {
            var listPaid =
                wareHouseContext.CustomerPaidHistories.Where(x => x.CustomerId == customerId && x.IsEnd == false).ToList();
            var result = listPaid.Sum(x => x.Amount);

            return result;
        }

        public List<CustomerPaidHistoryModel> GetCustomerPaidHistoryByCustomerId(int customerId)
        {
            var result = wareHouseContext.CustomerPaidHistories.Where(x => x.CustomerId == customerId && x.IsEnd == true && x.IsHaveItems == true).ToList().Select(Mapper.Map<CustomerPaidHistoryModel>);
            return result.ToList();
        }

        public List<DetailCustomerPaidHistoryModel> GetDetailCustomerPaidHistoryByCustomerPaidHistoryId(
            int customerPaidHistoryId)
        {
            var result = wareHouseContext.DetailCustomerPaidHistories.Where(x => x.CustomerPaidHistoryId == customerPaidHistoryId).ToList().Select(Mapper.Map<DetailCustomerPaidHistoryModel>);
            return result.ToList();
        }
        #endregion


        #region Report

        public List<ReportTotalEndDayModel> ReportExistByDay(int warehouseId, DateTime dateView)
        {
            var listResult = wareHouseContext.Items.ToList().Select(x => new ReportTotalEndDayModel
                {
                    ItemId = x.ItemId,
                    Stt = 0,
                    ItemName = x.ItemName,
                    TotalQuantity =
                        x.ImportDetails.ToList().Where(c => c.Import != null && c.Import.WareHouseId == warehouseId && c.Import.DateCreate.Date <= dateView.Date).Sum(y => y.Quantity) 
                        - x.ExportDetails.ToList().Where(c => c.Export != null && c.Export.WareHouseId == warehouseId && c.Export.DateCreate.Date < dateView.Date).Sum(y => y.Quantity),
                    QuantitySale =
                        x.ExportDetails.ToList().Where(c => c.Export != null && c.Export.WareHouseId == warehouseId && c.Export.DateCreate.Date == dateView.Date).Sum(y => y.Quantity),
                       QuantityExist = 0
                }).ToList();
            // build so luong con lai
            if (listResult.Any())
            {
                for (int i = 0; i < listResult.Count(); i++)
                {
                    listResult[i].QuantityExist = listResult[i].TotalQuantity - listResult[i].QuantitySale;
                }
                return listResult.ToList();
            }
            return null;
        }

        public List<ReportTotalEndDayDetailModel> ReportExistDetailByDay(int warehouseId, DateTime dateView)
        {
             var result =
                wareHouseContext.ExportDetails.ToList().Where(x => x.Export != null && (x.Export.WareHouseId == warehouseId && x.Export.DateCreate.Date == dateView.Date)).Select(
                    d =>
                    new ReportTotalEndDayDetailModel
                        {
                            ExportId = d.ExportId,
                            CurrentPrice = (float)d.ItemPrice.Value,
                            ItemId = d.ItemId,
                            ItemName = d.Item.ItemName,
                            Quantity = d.Quantity,
                            Total = (float)(d.Quantity * d.ItemPrice.Value),
                            CustomerId = d.Export.CustomerId,
                            CustomerName = d.Export.Customer.FullName,
                            IsDebt = d.Export.IsDebt
                        }).ToList();
            return result;
        }


        #endregion



        #region Order

        public string GetOrder()
        {

            var Order = wareHouseContext.Orders.OrderByDescending(x => x.OrderId).FirstOrDefault();
            var OrderId = "";
            if (Order != null)
            {
                var id = int.Parse(Order.OrderId.Substring(3));
                id += 1;
                OrderId = "DH" + string.Format("{0:00}", id);
                return OrderId;

            }
            OrderId = "DH01";
            return OrderId;
        }


        public bool SaveOrder(OrderModel model)
        {
            try
            {



                var entity = Mapper.Map<Order>(model);

                // update
                wareHouseContext.Orders.Add(entity);
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                throw ex;
            }


        }

        public bool SaveOrderDetail(List<OrderDetailModel> listModel, OrderModel OrderModel)
        {
            try
            {
                var listEntity = Mapper.Map<List<OrderDetailModel>, List<OrderDetail>>(listModel);

                // update
                foreach (var item in listEntity)
                {
                    wareHouseContext.OrderDetails.Add(item);

                    


                }
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        public List<OrderModel> ListAllOrder()
        {
           
            var result =
                wareHouseContext.Orders.Select(
                    x =>
                    new OrderModel()
                    {
                        IsFinish = x.IsFinish,
                        DateCreate = x.DateCreate,
                         OrderId= x.OrderId,
                        LastUpdate = x.LastUpdate,
                        UpdateBy = x.UpdateBy,
                        UserCreate = x.UserCreate,
                        CompanyId = x.CompanyId,
                        CompanyName = x.Company.CompanyName,
                        EmployerName = x.UserAccount.FullName

                    }).ToList();
            return result;

        }
        public List<OrderDetailModel> ListItemByOrderId(string OrderId)
        {
            var result =
                wareHouseContext.OrderDetails.Where(x => x.OrderId == OrderId).Select(
                    d =>
                    new OrderDetailModel()
                    {
                        OrderId = d.OrderId,
                        Price = d.Price,
                        ItemId = d.ItemId,
                        ItemName = d.Item.ItemName,
                        Quantity = d.Quantity,
                        Total = d.Quantity * d.Price
                    }).ToList();
            return result;
        }

        public bool UpdateStatusFinishOrnotForOrder(OrderModel model)
        {
            var entity = Mapper.Map<Order>(model);
            if (!string.IsNullOrEmpty(model.OrderId))
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<Order>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.OrderId == entity.OrderId);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return true;
            }
            return false;

        }
        #endregion

        #region UserAccount Hoang.Nguyen Minh
        public List<UserAccountModel> ListUserAccountWithoutAdministrator()
        {

            var listUserAccount = wareHouseContext.UserAccounts
                   .ToList().Where(x=>x.UserName.ToLower()!="administrator").Select(x=>new UserAccountModel
                   {
                       UserName = x.UserName,
                       DateCreate = x.DateCreate,
                       Dob = x.Dob,
                       Email = x.Email,
                       FirstName = x.FirstName,
                       FullName = x.FullName,
                       GroupUserId = x.GroupUserId,
                       HomePhone = x.HomePhone,
                       IdCard = x.IdCard,
                       IsAdmin = x.IsAdmin,
                       LastName = x.LastName,
                       LastUpdate = x.LastUpdate,
                       MiddleName = x.MiddleName,
                       MobilePhone = x.MobilePhone,
                       Password = x.Password,
                       UpdateBy = x.UpdateBy,
                       UserCreate=x.UserCreate,
                       GroupUserName = x.GroupUser.GroupUserName
                       
                   }).ToList();

            return listUserAccount;
        }


        public UserAccountModel SaveOrUpdateUserAccount(UserAccountModel model, bool isNewAccount)
        {
            var passEncrypt = MD5Encrypt(model.Password);
            model.Password = passEncrypt;
            var entity = Mapper.Map<UserAccount>(model);
            if (!isNewAccount)
            {

                // update


                var entry = wareHouseContext.Entry(entity);

                if (entry.State == EntityState.Detached)
                {
                    var set = wareHouseContext.Set<UserAccount>();
                    var attachedEntity = set.Local.FirstOrDefault(d => d.UserName == entity.UserName);  // You need to have access to key

                    if (attachedEntity != null)
                    {
                        var attachedEntry = wareHouseContext.Entry(attachedEntity);
                        attachedEntry.CurrentValues.SetValues(entity);
                    }
                    else
                    {
                        entry.State = EntityState.Modified; // This should attach entity
                    }
                    wareHouseContext.SaveChanges();
                }
                return Mapper.Map<UserAccountModel>(entity);
            }
            // update
            wareHouseContext.UserAccounts.Add(entity);
            
            wareHouseContext.SaveChanges();
            
            return Mapper.Map<UserAccountModel>(entity);

        }

        public bool DeleteUserAccount(UserAccountModel model)
        {
            try
            {
                using (var context = new WarehouseManagementEntities())
                {
                    var entity = Mapper.Map<UserAccount>(model);
                    context.UserAccounts.Attach(entity);
                    context.UserAccounts.Remove(entity);
                    context.SaveChanges();
                    return true;
                }
            }
            catch (Exception)
            {

                return false;
            }
        }

        public string ResetPasswordByUserName(string username)
        {
            try
            {
                var entity = wareHouseContext.UserAccounts.FirstOrDefault(x => x.UserName == username);
                var newPassEncrypt = MD5Encrypt(defaultPasswordReset);
                entity.Password = newPassEncrypt;
                wareHouseContext.SaveChanges();
                return defaultPasswordReset;
            }
            catch (Exception)
            {
                
                return "";
            }
           

        }

        public bool ChangePassword(string username, string oldPass, string newPass)
        {
            var oldPassEncrypt = MD5Encrypt(oldPass);
            var entity = wareHouseContext.UserAccounts.FirstOrDefault(x => x.UserName == username && x.Password == oldPassEncrypt);
            
            if (entity !=null)
            {
                var newPassEncrypt = MD5Encrypt(newPass);
                entity.Password = newPassEncrypt;
                wareHouseContext.SaveChanges();
                return true;
            }

            
            return false;
        }

        #endregion


        #region Permit
        public bool DeleteAllRoleByGroupUserId(int groupUserId)
        {
            try
            {
                var listRoleDelete = wareHouseContext.Detail_GroupUserRole.Where(x => x.GroupUserId == groupUserId).ToList();
                foreach (var item in listRoleDelete)
                {
                    wareHouseContext.Detail_GroupUserRole.Remove(item);
                }
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception)
            {

                return false;
            }
            
           

        }

        public List<DetailGroupUserRoleModel> GetDetailRoleByGroupUserId(int groupUserId)
        {
           var result= wareHouseContext.Detail_GroupUserRole.ToList().Where(x => x.GroupUserId == groupUserId);
            return result.Select(x=>new DetailGroupUserRoleModel
                {
                    GroupUserId = x.GroupUserId,
                    GroupUserName = x.GroupUser.GroupUserName,
                    Permit = (bool)x.Permit,
                    RoleId = x.RoleId,
                    RoleName = x.Role.RoleName,
                    GroupRoleId = x.Role.GroupRoleId,
                    GroupRoleName = x.Role.GroupRole.GroupRoleName
                }).ToList();
        }


        public bool SaveListRoleForGroupUser(List<DetailGroupUserRoleModel> listModel)
        {
            try
            {
                foreach (var item in listModel)
                {
                    var entity = Mapper.Map<Detail_GroupUserRole>(item);
                    wareHouseContext.Detail_GroupUserRole.Add(entity);
                }
                wareHouseContext.SaveChanges();
                return true;
            }
            catch (Exception)
            {

                return false;
            }
            

        }

        public bool R(int groupUserId, string roldId)
        {
            var result =
                wareHouseContext.Detail_GroupUserRole.FirstOrDefault(x => x.GroupUserId == groupUserId && x.RoleId == roldId);
            return (bool) (result != null ? result.Permit : false);
        }
        #endregion
    }
}
